﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using System.Threading;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System.IO;

namespace COFE.Core.Plugin
{
    public class PluginManager : IPluginManager, IPartImportsSatisfiedNotification
    {

        #region Constructor

        public PluginManager(string pluginPath)
        {
            //pluginPath = pluginPath.TrimEnd('\\');
            using (var catalog = new DirectoryCatalog(pluginPath, "COFE.*.dll"))
            using (var container = new CompositionContainer(catalog))
            {
                container.ComposeParts(this);   
            }
        }

        #endregion

        #region Methods

        public void OnImportsSatisfied()
        {
            _plugins.AddRange(_import_plugins.OrderBy(p => p.Priority));
            _pluginUsers.AddRange(_import_pluginUsers.OrderBy(u => u.Priority));
            _pluginLock.Set();
            foreach (var user in _pluginUsers)
                user.Apply(this);
        }

        #endregion

        #region Data

        private ManualResetEvent _pluginLock = new ManualResetEvent(false);

        private List<IPlugin> _plugins = new List<IPlugin>();
        private List<IPluginUser> _pluginUsers = new List<IPluginUser>();

        [ImportMany(typeof(IPlugin))]
        private IEnumerable<IPlugin> _import_plugins { get; set; }

        [ImportMany(typeof(IPluginUser))]
        private IEnumerable<IPluginUser> _import_pluginUsers { get; set; }

        #endregion

        #region Public Properties

        public List<IPlugin> Plugins
        {
            get
            {
                if (_pluginLock.WaitOne(TimeSpan.FromMinutes(1)))
                    return _plugins;
                else return new List<IPlugin>();
            }
        }

        public List<IPluginUser> PluginUser
        {
            get
            {
                if (_pluginLock.WaitOne(TimeSpan.FromMinutes(1)))
                    return _pluginUsers;
                else return new List<IPluginUser>();
            }
        }

        public IEnumerable<P> GetPlugins<P>() where P : IPlugin
        {
            return from p in Plugins where p is P select (P)p;
        }



        #endregion












        
    }
}
